//
//                 rtmeus.cpp: written by T.Yoshikai 2010/05/24
//

#include "rtmeus.h"

//Member function for RTMEusComp
RTMEusComp::RTMEusComp(const char* cpath, const char* cname, bool cflag)
{
    strncpy(m_componentpath, (char *)cpath, strlen(cpath));
    m_componentpath[strlen(cpath)]='\0';
    strncpy(m_componentname, cname, strlen(cname));
    m_componentname[strlen(cname)]='\0';

    createflag = cflag;
    if(createflag==true) strncpy(&(m_componentname[strlen(cname)]), ".rtc\0", 5);
}

RTMEusComp::RTMEusComp(const char* cpath, const char* cname, bool cflag, RTMEUS::StateService_var svc)
{
    strncpy(m_componentpath, (char *)cpath, strlen(cpath));
    m_componentpath[strlen(cpath)]='\0';
    strncpy(m_componentname, cname, strlen(cname));
    m_componentname[strlen(cname)]='\0';

    createflag = cflag;
    if(createflag==true) strncpy(&(m_componentname[strlen(cname)]), ".rtc\0", 5);
    stsvc = svc;
}

RTMEusComp::~RTMEusComp()
{    
    if(createflag==true) Destroy();
}

std::string RTMEusComp::Activate()
{
    return RTMEus::CommandExec("rtact", m_componentpath);
}

std::string RTMEusComp::Deactivate()
{
    return RTMEus::CommandExec("rtdeact", m_componentpath);
}

std::string RTMEusComp::SetConfiguration(const char* configvar, const char* config)
{
    char cargs[256];
    sprintf(cargs, "%s set %s %s", m_componentpath, configvar, config);
    return RTMEus::CommandExec("rtconf", cargs);
}

std::string RTMEusComp::Destroy()
{
    RTMEus::CommandExec("rtdel", m_componentpath);
    return std::string(":success");
}

std::string RTMEusComp::GetComponentPath()
{
    return std::string(m_componentpath);
}

std::string RTMEusComp::GetComponentName()
{
    return std::string(m_componentname);    
}

std::string RTMEusComp::ShowComponentInfo(int showlevel)
{
    std::string result;
        
    switch(showlevel){
    case 0:
        result = RTMEus::CommandExec("rtcat", m_componentpath);
        break;
    case 1:
        result = RTMEus::CommandExec("rtcat -l", m_componentpath);
        break;
    case 2:
        result = RTMEus::CommandExec("rtcat -ll", m_componentpath);
        break;
    default:
        result = RTMEus::CommandExec("rtcat", m_componentpath);
        break;
    }

    std::cerr << result << std::endl;
    return std::string(":success");
}

std::string RTMEusComp::InputData(const char* port, const char* datatype, const char* data)
{
    char cargs[256];
    sprintf(cargs, "%s:%s -c 'RTC.%s({time}, %s)' -n 1 -r 1000", m_componentpath, port, datatype, data);
    
    RTMEus::CommandExec("rtinject", cargs);
    
    return std::string(":success");
}

std::string RTMEusComp::ReceiveData(const char* port, const char* datatype)
{
    std::string result;
    char cargs[256];
    std::stringstream ss;
    std::vector<std::string> rets;

    sprintf(cargs, "%s:%s -n 1 -r 1000", m_componentpath, port);
    
    result = RTMEus::CommandExec("rtprint", cargs);

    ss << result;
    while(1){
      std::string str;
      getline(ss, str);
      if(str.empty() == true) break;
      else rets.push_back(str);
    }

    if(rets.size() > 1){
      if(strcmp(datatype, "TimedShortSeq")==0 || strcmp(datatype, "TimedLongSeq")==0 || strcmp(datatype, "TimedFloatSeq")==0 || strcmp(datatype, "TimedDoubleSeq")==0){	
	char* src = (char*)rets[1].c_str();
	char* token;
	token = strtok(src, "] ");      
	token = strtok(NULL, "]");      
	
	char* ary = &(token[2]);
	std::vector<std::string> rv;
	token = strtok(ary, ",");	
	while(token != NULL){
	  rv.push_back(std::string(token));
	  token = strtok(NULL, ",");
	}

	std::stringstream ss;
	if(strcmp(datatype, "TimedShortSeq")==0 || strcmp(datatype, "TimedLongSeq")==0){
	  ss << "#i(";
	} else if(strcmp(datatype, "TimedFloatSeq")==0 || strcmp(datatype, "TimedDoubleSeq")==0){
	  ss << "#f(";
	}
	for(unsigned int i=0;i<rv.size();i++){
	  ss << rv[i];
	  ss << " ";
	}
	ss << ")";

	return ss.str();
      } else {
	//just an atom
	char* src = (char*)rets[1].c_str();
	char* token;
	token = strtok(src, "] ");      
	token = strtok(NULL, " ");      
	
	return token;
      }
    } else return rets[0];
}

std::string RTMEusComp::GetStates(std::vector<std::string> strnames)
{
    std::stringstream ss;
    RTMEUS::StateList* stlist;
    RTMEUS::StateProfileList* splist;
    RTMEUS::StateNameList *names = new RTMEUS::StateNameList(strnames.size());    
    
    names->length(strnames.size());

    for(unsigned int i=0;i<strnames.size(); i++) (*names)[i] = strnames[i].c_str();

    try{
        stlist = stsvc->get_states(*names);
        splist = stsvc->get_state_profiles();
	
        for(CORBA::ULong i(0); i < (*names).length(); i++){
            StatePtr st;
            RTMEUS::StateType type=(*splist)[0].type;;
            CORBA::ULong j;
            for(j=0; j < (*splist).length(); j++){
                if(strcmp((*names)[i], (*splist)[j].name)==0){
                    st = StatePtr(StateBase::create((*splist)[j]));
                    type = (*splist)[j].type;
                    break;
                }
            }

            if(j==(*splist).length()){
                return std::string("nil!");
            }
            (*stlist)[i].data >>= st;

            if(type == RTMEUS::CHARSEQ_TYPE){
                ss << "c ";
                for(unsigned int k=0; k < (unsigned int)st->getLength(); k++) ss << (short)*(unsigned char*)st->getPtr(k) << " ";
            } else if(type == RTMEUS::SHORTSEQ_TYPE) {
                ss << "s ";
                for(unsigned int k=0; k < (unsigned int)st->getLength(); k++) ss << *(short*)st->getPtr(k) << " ";
            } else if(type == RTMEUS::LONGSEQ_TYPE) {
                ss << "l ";
                for(unsigned int k=0; k < (unsigned int)st->getLength(); k++) ss << *(long*)st->getPtr(k) << " ";
            } else if(type == RTMEUS::FLOATSEQ_TYPE) {
                ss << "f ";
                for(unsigned int k=0; k < (unsigned int)st->getLength(); k++) ss << *(float*)st->getPtr(k) << " ";
            } else if(type == RTMEUS::DOUBLESEQ_TYPE) {
                ss << "d ";
                for(unsigned int k=0; k < (unsigned int)st->getLength(); k++) ss << *(double*)st->getPtr(k) << " ";
            }
            if(i!=((*names).length()-1))ss << ",";
        }

	delete stlist;
	delete splist;
    } catch(...){
        std::cerr << "StateService Error" << std::endl;
    }

    delete names;
    
    return ss.str();
}

std::string RTMEusComp::SetStates(coil::Properties prop)
{    
    std::string ret;
    StateManager SStateManger;
    RTMEUS::StateList_var statelist = new RTMEUS::StateList();
    std::vector<coil::Properties *> props;

    props = prop.getLeaf();
    for(unsigned int i=0; i < props.size(); i++) SStateManger.addState(StatePtr(StateBase::create(*props[i])));

    SStateManger.copyToStateList(statelist);

    try{
        stsvc->set_states(statelist);
    } catch(...){
        std::cerr << "StateService Error" << std::endl;
    }

    return std::string(":set-states ok");
}

//Member function for RTMEusManager
RTMEusManager::RTMEusManager(char* host, int port, int manager_no)
{
    const char* mpath;

    mpath = (const char*)(CreateManager(host, port, manager_no).c_str());
    strncpy(m_managerpath, (char *)mpath, strlen(mpath)-1);
    m_managerpath[strlen(mpath)-1]='\0';    
    strncpy(m_host, host, strlen(host));

    std::cerr << "New Manager[manager" << manager_no << ".mgr] is created." << std::endl;
}

RTMEusManager::~RTMEusManager()
{
    RTMEus::CommandExec("rtdel", m_managerpath);
    m_manager=NULL;
}

int charstring2int(char* str){
  int sum=0, tmp=0;

  for(unsigned int i=0;i<strlen(str);i++){
    tmp = str[i];
    sum += tmp;
  }
  
  return tmp;
}

std::string RTMEusManager::CreateManager(char* host, int port, int manager_no)
{
    // rtc.conf用のテンポラリファイルをつくる
    char *argv[4];
    char tmp_file[] = "/tmp/rtcconf.XXXXXX";
    char uq_manager_label[] = "XXXXXX";
    char *tmpfilename;
    char *unique_manager_label;
    int unique_number;
    char cargs[64];
    const char* mpath;
    std::string uname;

    tmpfilename = mktemp(tmp_file);
    std::fstream fstrm(tmp_file, std::ios::out);
    if (fstrm.fail()) {
        std::cerr << "failed to open temporary file" << std::endl;
        goto exit;
    }

    unique_manager_label = mktemp(uq_manager_label);
    unique_number = charstring2int(unique_manager_label); 

    fstrm << "corba.nameservers: " << host << ":" << port << std::endl;
    fstrm << "logger.enable: NO" << std::endl;
    fstrm << "manager.instance_name: rtmeus_manager" << unique_manager_label << std::endl;
    fstrm << "corba.master_manager:" << host << ":" << (MANBASEPORT+unique_number+manager_no) << std::endl;

    fstrm << "manager.modules.load_path: ./" << std::endl;
    fstrm << "manager.modules.abs_path_allowed: yes" << std::endl;
    
    fstrm.close();
    //
    argv[0] = (char *)"eus1"; 
    argv[1] = (char *)"-f";
    argv[2] = tmp_file;
    argv[3] = (char *)"-d";

    try {
        m_manager = RTC::Manager::init(4, argv);
        m_manager->activateManager();
        char host_str[256];
        sprintf(host_str, "%s:%d", host, port);
        m_naming = new RTC::CorbaNaming(m_manager->getORB(), host_str);
    } catch(...) {
        std::cerr << "failed to create rtc manager" << std::endl;
        exit(0);
    }

exit:;
    // テンポラリファイルの削除
    remove(tmp_file);

    sprintf(cargs, "/%s --name=%s.mgr --type=m", host, unique_manager_label);
    std::string tmpstr(RTMEus::CommandExec("rtfind", cargs));
    mpath = static_cast<const char*>(tmpstr.c_str());

    return std::string(mpath);
}

std::string RTMEusManager::LoadModule(const char* sopath, const char* initfuncname)
{
    char cargs[256];

    sprintf(cargs, "--load=%s --init-func=%s %s", sopath, initfuncname, m_managerpath);
    return RTMEus::CommandExec("rtmgr", cargs);
}

std::string RTMEusManager::UnLoadModule(const char* sopath)
{
    char cargs[256];

    sprintf(cargs, "--unload=%s %s", sopath, m_managerpath);
    
    return RTMEus::CommandExec("rtmgr", cargs);    
}

std::string RTMEusManager::CreateModule(const char* classname, const char* instancename, double exec_rate, const char* exec_type)
{
    char cargs1[256];
    const char* cpath;
    char rate_str[16];

    sprintf(rate_str,"%7.2lf", exec_rate);
    m_manager->getConfig().setProperty("exec_cxt.periodic.type", exec_type);
    m_manager->getConfig().setProperty("exec_cxt.periodic.rate", rate_str);
    m_manager->getConfig().setProperty("naming.formats", "%h.host_cxt/%n.rtc");
    sprintf(cargs1, "--create=%s?instance_name=%s  %s", classname, instancename, m_managerpath);
    RTMEus::CommandExec("rtmgr", cargs1);
    //necessary sleep 500ms
    usleep((500 * 1000));

    char cargs2[256];    
    sprintf(cargs2, "/%s --name=%s --type=c", m_host, instancename);
    cpath = RTMEus::CommandExec("rtfind", cargs2).c_str();

    return std::string(cpath);
}

CORBA::Object_ptr RTMEusManager::UseServiceFromManager(const char* rtcpath, const char* servicetype, const char* serviceinterface)
{
    std::string tmppath = std::string(rtcpath);
    //erase first '/'
    tmppath.erase(0, 1);
    char *tp;
    tp = strtok((char*)tmppath.c_str(), "/");

    //pathを整形 /xx.xx.xx.xx/ を削除
    std::string rtcpath_for_resolve = std::string(rtcpath);    
    rtcpath_for_resolve.erase(0, (strlen(tp)+2));
    
    // RTObjectを取得
    CORBA::Object_var obj = m_naming->resolve(rtcpath_for_resolve.c_str());
    RTC::RTObject_var rtc = RTC::RTObject::_narrow(obj);

    // ComponentProfileを取得
    RTC::ComponentProfile_var prof;
    prof = rtc->get_component_profile();

    // PortProfileを取得
    RTC::PortProfileList port_prof;
    port_prof = prof->port_profiles;

    int portno=0;
    char instancename[128];
    //instancenameを取得
    std::vector<std::string> sv;
    while(tp != NULL){
      sv.push_back(std::string(tp));
      tp = strtok(NULL, "/");      
    }

    strcpy(instancename, sv.back().c_str());
    char* endpoint = strstr(instancename, ".rtc");
    *endpoint = '\0';
    
    std::string searchname = std::string(instancename) + std::string(".") + std::string(servicetype);
    for (CORBA::ULong i(0), len(port_prof.length()); i < len; ++i)
      if(strcmp(port_prof[i].name, searchname.c_str())==0) portno = i;

    RTC::PortService_var port;
    port = port_prof[portno].port_ref;

    // ConnectorProfile のportメンバに自分自身のリファレンスのみ入れて
    // connect する。戻ってきたConnectorProfileのpropertiesの中には
    // サービスのObjectReferenceが入っているので取得する。
    RTC::ConnectorProfile con_prof;
    con_prof.name = CORBA::string_dup("testconnect");
    con_prof.connector_id = "";
    con_prof.ports.length(1);
    con_prof.ports[0] = RTC::PortService::_duplicate(port);
    con_prof.properties.length(0);
    if (CORBA::is_nil(port))
    {
        std::cout << "nil reference" << std::endl;
    }
    if (port->connect(con_prof) != RTC::RTC_ERROR)
    {
        // エラーは無視
    }   
    // NVUtilでpropertiesの中からサービスのオブジェクトリファレンスを取得
    // IORなのでstring_to_objectしなければならない
    std::string portname = std::string("port.") + std::string(servicetype) + std::string(".") + std::string(serviceinterface);
    std::string iorvalue = NVUtil::toString(con_prof.properties, portname.c_str());        
    return m_manager->getORB()->string_to_object(iorvalue.c_str());
}

std::string RTMEusManager::SendCommandFromManager(const char* rtcpath, const char* command, const char* argv)
{
    const char* ret = "";

    CORBA::Object_ptr aobj = UseServiceFromManager(rtcpath, "CommandService","commandservice");
    RTMEUS::CommandService_var cmdsvc = RTMEUS::CommandService::_narrow(aobj);

    try{
        ret = cmdsvc->command(command, argv);        
    } catch(...){
        std::cerr << "CommandService Error" << std::endl;
    }

    return std::string(ret);
}

void RTMEusManager::SetPluginModeFromManger(const char* leader_rtcname, std::vector<std::string> attatched_rtcnames)
{
    char hostname[24];
    char compname[128];
    std::vector<RTC::RTObject_var> artcs;
    
    gethostname(hostname, sizeof(hostname));
    sprintf(compname, "%s.host_cxt/%s", hostname, leader_rtcname);

    // RTObjectを取得
    CORBA::Object_var obj = m_naming->resolve(compname);
    RTC::RTObject_var lrtc = RTC::RTObject::_narrow(obj);

    //一旦止める
    RTC::ExecutionContextList_var lecs;
    lecs = lrtc->get_owned_contexts();
    lecs[(CORBA::ULong)0]->stop();

    //追加するものも止める
    for(unsigned int i=0;i<attatched_rtcnames.size();i++){
        char acompname[128];
        sprintf(acompname, "%s.host_cxt/%s", hostname, attatched_rtcnames[i].c_str());
        CORBA::Object_var tobj = m_naming->resolve(acompname);
        artcs.push_back(RTC::RTObject::_narrow(tobj));
        RTC::ExecutionContextList_var ecs;
        ecs = artcs[i]->get_owned_contexts();
        ecs[(CORBA::ULong)0]->stop();
    }

    //一個にまとめる
    for(unsigned int i=0;i<artcs.size();i++)
        lecs[(CORBA::ULong)0]->add_component(artcs[i]);

    //再開する
    lecs[(CORBA::ULong)0]->start();
}

void RTMEusManager::PluginModeAllActivateFromManager(const char* leader_rtcname, std::vector<std::string> attatched_rtcnames, int interval)
{
    char hostname[24];
    char compname[128];
    
    gethostname(hostname, sizeof(hostname));
    sprintf(compname, "%s.host_cxt/%s", hostname, leader_rtcname);

    // RTObjectを取得
    CORBA::Object_var obj = m_naming->resolve(compname);
    RTC::RTObject_var lrtc = RTC::RTObject::_narrow(obj);

    //まず自分自身をactivate
    RTC::ExecutionContextList_var lecs;
    lecs = lrtc->get_owned_contexts();
    lecs[(CORBA::ULong)0]->activate_component(lrtc);
    usleep(interval);

    //他のも全部activate
    for(unsigned int i=0;i<attatched_rtcnames.size();i++){
        char acompname[128];
        sprintf(acompname, "%s.host_cxt/%s", hostname, attatched_rtcnames[i].c_str());
        CORBA::Object_var tobj = m_naming->resolve(acompname);
        lecs[(CORBA::ULong)0]->activate_component(RTC::RTObject::_narrow(tobj));
        usleep(interval);
    }
}

void RTMEusManager::PluginModeAllDeactivateFromManager(const char* leader_rtcname, std::vector<std::string> attatched_rtcnames)
{
    char hostname[24];
    char compname[128];
    
    gethostname(hostname, sizeof(hostname));
    sprintf(compname, "%s.host_cxt/%s", hostname, leader_rtcname);

    // RTObjectを取得
    CORBA::Object_var obj = m_naming->resolve(compname);
    RTC::RTObject_var lrtc = RTC::RTObject::_narrow(obj);
    RTC::ExecutionContextList_var lecs;
    lecs = lrtc->get_owned_contexts();

    //まず他のを全部deactivate
    for(unsigned int i=0;i<attatched_rtcnames.size();i++){
        char acompname[128];
        sprintf(acompname, "%s.host_cxt/%s", hostname, attatched_rtcnames[i].c_str());
        CORBA::Object_var tobj = m_naming->resolve(acompname);
        lecs[(CORBA::ULong)0]->deactivate_component(RTC::RTObject::_narrow(tobj));
    }
    //最後に自分自身をdeactivate
    lecs[(CORBA::ULong)0]->deactivate_component(lrtc);
}

//Member function for RTMEus
RTMEus::RTMEus(char* host, int port, int manager_no){
    rtmeus_manager = new RTMEusManager(host, port, manager_no);
}

RTMEus::~RTMEus(){    
    for(unsigned int i=0;i<comps.size();i++) delete comps[i];
    delete rtmeus_manager;        
}

std::string RTMEus::LoadModule(const char* sopath, const char* initfuncname)
{
    return rtmeus_manager->LoadModule(sopath, initfuncname);
}

int RTMEus::CreateComponent(const char* classname, const char* instancename, double exec_rate, const char* exec_type, bool sflag)
{
    std::stringstream ss;
    std::string cpath, tpath;
    std::vector<std::string> ccpaths;
    std::string rtcname = std::string(instancename) + std::string(".rtc");

    cpath = rtmeus_manager->CreateModule(classname, instancename, exec_rate, exec_type);
    ss << cpath;
    std::cerr << "Component " << instancename << " is created." << std::endl;
    while(1){
        std::string str;
        getline(ss, str);
        if(str.empty() == true) break;
        else ccpaths.push_back(str);
    }

    for(int i = 0 ;i< (int)ccpaths.size();i++)
      if(ccpaths[i].find(".mgr", 0) == std::string::npos){
	tpath = ccpaths[i];
	break;}

    std::cerr << "Created component path is " << tpath << std::endl;
    if(sflag==true) {
        CORBA::Object_ptr aobj = rtmeus_manager->UseServiceFromManager(tpath.c_str(), "StateService","stateservice");
        RTMEUS::StateService_var svc = RTMEUS::StateService::_narrow(aobj);
        comps.push_back(new RTMEusComp(tpath.c_str(), instancename, true, svc));
    } else {
        comps.push_back(new RTMEusComp(tpath.c_str(), instancename, true));        
    }
    return (comps.size()-1);
}

int RTMEus::ResolveComponent(const char* searchpath, const char* instancename, bool sflag)
{
    char cargs[256];
    std::stringstream ss;
    std::string cpath, tpath;
    std::vector<std::string> ccpaths;
    char paths[256];

    sprintf(cargs, "%s --name=/%s --type=c", searchpath, instancename);
    cpath = RTMEus::CommandExec("rtfind", (const char*)cargs);
    if(strcmp(cpath.c_str(), "")==0){
      std::cerr << instancename << " in " << searchpath << " : No such component!" << std::endl;
        return -1;
    }

    ss << cpath;
    while(1){
        std::string str;
        getline(ss, str);
        if(str.empty() == true) break;
        else ccpaths.push_back(str);
    }

    for(int i = 0 ;i< (int)ccpaths.size();i++)
      if(ccpaths[i].find(".mgr", 0) == std::string::npos){
	tpath = ccpaths[i];
	break;}

    strcpy(paths, (char*)tpath.c_str());
    std::cerr << "Component " << instancename << " is resolved." << std::endl;

    for(unsigned int i=0;i<comps.size();i++){
        if(strncmp(paths, (char*)(comps[i]->GetComponentPath().c_str()),(strlen(paths)-1)) == 0){
	  std::cerr << instancename << ": Already registerd!" << std::endl;
            return -1;
        }
    }

    if(sflag==true) {
      CORBA::Object_ptr aobj = rtmeus_manager->UseServiceFromManager(tpath.c_str(), "StateService","stateservice");
      RTMEUS::StateService_var svc = RTMEUS::StateService::_narrow(aobj);
      comps.push_back(new RTMEusComp(tpath.c_str(), instancename, false, svc));
    } else {
      comps.push_back(new RTMEusComp(tpath.c_str(), instancename, false));
    }
    
    return (comps.size()-1);
}

int RTMEus::FindComponent(const char* searchpath, const char* instancename)
{
    char cargs[256];
    std::stringstream ss;
    std::string cpath, ccpath;

    sprintf(cargs, "%s --name=%s --type=c", searchpath, instancename);
    cpath = RTMEus::CommandExec("rtfind", (const char*)cargs);
    if(strcmp(cpath.c_str(), "")==0){
      std::cerr << instancename << " in " << searchpath << " : No such component!" << std::endl;
        return -1;
    }
    return 0;
}

std::string RTMEus::ConnectComponents(const char* outRtcPath, const char* outPort, const char* inRtcPath, const char* inPort, int subscriptionType)
{
    char cargs[256];
    
    if(outRtcPath!=NULL && inRtcPath!=NULL){
      switch(subscriptionType){
      case 0:
        sprintf(cargs, "%s:%s %s:%s -p dataport.subscription_type=flush",outRtcPath, outPort, inRtcPath, inPort);
	break;
      case 1:
        sprintf(cargs, "%s:%s %s:%s -p dataport.subscription_type=new",outRtcPath, outPort, inRtcPath, inPort);
	break;
      case 2:
        sprintf(cargs, "%s:%s %s:%s -p dataport.subscription_type=periodic",outRtcPath, outPort, inRtcPath, inPort);
	break;
      default:
        sprintf(cargs, "%s:%s %s:%s -p dataport.subscription_type=flush",outRtcPath, outPort, inRtcPath, inPort);
	break;
      }
      return RTMEus::CommandExec("rtcon", cargs);
    } else return std::string(":connect-fail");
}

std::string RTMEus::DisconnectComponents(const char* outRtcPath, const char* outPort, const char* inRtcPath, const char* inPort)
{
    char cargs[256];
    
    if(outRtcPath!=NULL && inRtcPath!=NULL){
        sprintf(cargs, "%s:%s %s:%s",outRtcPath, outPort, inRtcPath, inPort);
        return RTMEus::CommandExec("rtdis", cargs);
    } else return std::string(":disconnect-fail");
}

RTMEusComp* RTMEus::GetComponent(int component_no)
{
    if(component_no < 0 || (int)comps.size() <= component_no) return NULL;

    return comps[component_no];
}

std::string RTMEus::SendCommandService(const char* comppath, const char* command, const char* argv)
{
    std::string ret;
    ret = rtmeus_manager->SendCommandFromManager(comppath, command, argv);
    
    return ret;
}

void RTMEus::SetPluginMode(const char* leader_rtcname, std::vector<std::string> attatched_rtcnames)
{
    rtmeus_manager->SetPluginModeFromManger(leader_rtcname, attatched_rtcnames);
}

void RTMEus::PluginModeAllActivate(const char* leader_rtcname, std::vector<std::string> attatched_rtcnames, int interval)
{
    rtmeus_manager->PluginModeAllActivateFromManager(leader_rtcname, attatched_rtcnames, interval);
}

void RTMEus::PluginModeAllDeactivate(const char* leader_rtcname, std::vector<std::string> attatched_rtcnames)
{
    rtmeus_manager->PluginModeAllDeactivateFromManager(leader_rtcname, attatched_rtcnames);
}

std::string RTMEus::CommandExec(const char* command, const char* args)
{
    char comstr[256];
    char buf[1024];
    char rbuf[1024];
    int ret;
    char *p;
    FILE *exec_shell;
    std::string outstr;

    outstr.reserve(128);

    memset(buf, '\0', sizeof(buf));
    memset(rbuf, '\0', sizeof(buf));
    p = &(rbuf[0]);

    sprintf(comstr, "%s %s", command, args);
    exec_shell = popen(comstr, "r");

    if(exec_shell != NULL){
        while((ret=fread(buf, sizeof(char), 1024, exec_shell)) > 0)
        {
            strncpy(p, buf, ret);
            p+=ret;
        }
    } else {
        pclose(exec_shell);
        return std::string(":fail");
    }
    pclose(exec_shell);

    outstr += rbuf;
    return outstr;
}
